package top.heathylife.pagehelperx.wrappers;

import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import top.heathylife.pagehelperx.other.BusinessException;
import top.heathylife.pagehelperx.other.TypeFunction;
import top.heathylife.pagehelperx.enums.Operator;
import top.heathylife.pagehelperx.factory.ConverterFactory;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;

/**
 * 功能描述: LambdaEntityWrapper
 *
 * @author maoxiaomeng
 * @date 20230531
 */
@Slf4j
public class LambdaEntityWrapper<T> {


    private List<Comparator<T>> comparators;

    private List<Predicate<T>> predicates;

    public LambdaEntityWrapper<T> eq(boolean condition, TypeFunction<T, ?> getter, Object value) {
        if (condition) {
            FunctionWrapper<T> fWrapper = new FunctionWrapper<>();
            fWrapper.setKey(getter);
            fWrapper.setValue(new Object[]{value});
            addFilter(Operator.EQ, fWrapper);
        }
        return this;
    }

    public LambdaEntityWrapper<T> eq(TypeFunction<T, ?> getter, Object value) {
        return eq(true, getter, value);
    }

    public LambdaEntityWrapper<T> like(boolean condition, TypeFunction<T, ?> getter, Object value) {
        if (condition) {
            FunctionWrapper<T> fWrapper = new FunctionWrapper<>();
            fWrapper.setKey(getter);
            fWrapper.setValue(new Object[]{value});
            addFilter(Operator.LIKE, fWrapper);
        }
        return this;
    }

    public LambdaEntityWrapper<T> like(TypeFunction<T, ?> getter, Object value) {
        return like(true, getter, value);
    }

    public LambdaEntityWrapper<T> between(boolean condition, TypeFunction<T, ?> getter, Object... value) {
        if (condition) {
            FunctionWrapper<T> fWrapper = new FunctionWrapper<>();
            fWrapper.setKey(getter);
            fWrapper.setValue(value);
            addFilter(Operator.BETWEEN, fWrapper);
        }
        return this;
    }

    public LambdaEntityWrapper<T> between(TypeFunction<T, ?> getter, Object... value) {
        return between(true, getter, value);
    }

    public LambdaEntityWrapper<T> filter(boolean condition, Predicate<T> predicate) {
        if (condition) {
            addFilter(Operator.FILTER_CUSTOM, predicate);
        }
        return this;
    }

    public LambdaEntityWrapper<T> filter(Predicate<T> predicate) {
        return filter(true, predicate);
    }


    public LambdaEntityWrapper<T> orderBy(Comparator<T> comparator) {
        return orderBy(true, comparator);
    }

    public LambdaEntityWrapper<T> orderBy(boolean condition, Comparator<T> comparator) {
        if (condition) {
            addOrderCondition(Operator.ORDER_BY_CUSTOM, null, comparator);
        }
        return this;
    }


    public LambdaEntityWrapper<T> orderByAsc(boolean condition, TypeFunction<T, ?> getter) {
        if (condition) {
            addOrderCondition(Operator.ORDER_BY_ASC, getter);
        }
        return this;
    }

    public LambdaEntityWrapper<T> orderByAsc(TypeFunction<T, ?> getter) {
        return orderByAsc(true, getter);
    }

    public LambdaEntityWrapper<T> orderByDesc(boolean condition, TypeFunction<T, ?> getter) {
        if (condition) {
            addOrderCondition(Operator.ORDER_BY_DESC, getter);
        }
        return this;
    }

    public LambdaEntityWrapper<T> orderByDesc(TypeFunction<T, ?> getter) {
        return orderByDesc(true, getter);
    }

    public void addFilter(@NonNull Operator operator, FunctionWrapper<T> wrapper) {
        addFilter(operator, wrapper, null);
    }


    public void addFilter(@NonNull Operator operator, Predicate<T> customPredicate) {
        addFilter(operator, null, customPredicate);
    }

    public void addFilter(@NonNull Operator operator, FunctionWrapper<T> wrapper, Predicate<T> customPredicate) {
        if (predicates == null) {
            predicates = new ArrayList<>(16);
        }
        Predicate<T> predicate;
        if (operator.equals(Operator.FILTER_CUSTOM)) {
            predicate = Optional.ofNullable(customPredicate).orElseThrow(() -> new BusinessException("自定义过滤器不允许为空"));
        } else {
            predicate = ConverterFactory.<T>getPredicateInstance(operator).toPredicate(wrapper);
        }
        predicates.add(predicate);
    }

    public void addOrderCondition(@NonNull Operator operator, TypeFunction<T, ?> key) {
        addOrderCondition(operator, key, null);
    }

    public void addOrderCondition(@NonNull Operator operator, TypeFunction<T, ?> key, Comparator<T> comparator) {
        if (comparators == null) {
            comparators = new ArrayList<>();
        }
        Comparator<T> orderComparator;
        if (operator.equals(Operator.ORDER_BY_CUSTOM)) {
            orderComparator = Optional.ofNullable(comparator).orElseThrow(() -> new BusinessException("自定义排序器不能为空"));
        } else {
            orderComparator = ConverterFactory.getOrderComparator(operator, key);
        }
        comparators.add(orderComparator);
    }

    public List<Predicate<T>> predicates() {
        return this.predicates;
    }

    public List<Comparator<T>> comparatorList() {
        return this.comparators;
    }


}
